#include <qstring.h>
#include <qstringbuilder.h>
#include <QMessageBox>
#include <QPainter>
#include <qimage.h>
#include <qimagereader.h>
#include "ps3tomidi.h"
#include "MidiMessage.h"

static bool R1_Down = false;
static bool L1_Down = false;
static bool R2_Down = false;
static bool L2_Down = false;
static bool R3_Down = false;
static bool L3_Down = false;
static bool Start_Down = false;
static bool Select_Down = false;
static bool Circle_Down = false;
static bool Cross_Down = false;
static bool Square_Down = false;
static bool Triangle_Down = false;
static bool Home_Down = false;

// POVs will have their own signals / slots -- TODO
static bool Up_Down = false;
static bool Right_Down = false;
static bool Down_Down = false;
static bool Left_Down = false;

PS3ToMidi::PS3ToMidi(QWidget *parent, Qt::WFlags flags)
	: QMainWindow(parent, flags)
{
	ui.setupUi(this);

	try {
		inDevMgr.init();
	} catch(DeviceManagerInitException &e) {
		QString error;
		error.sprintf("Device Manager failed to initialize with status: %x", e.getCode());
		QMessageBox::critical(this, QString("Device Manager Error"), error, QMessageBox::Ok);
		exit(1);
	}

	for (int i = 0; i < MidiOutDevice::getDeviceCount(); i++)
		ui.midiOutDevices->addItem(MidiOutDevice::getDeviceName(i));
	for (int i = 0; i < inDevMgr.getGamepadCount(); i++)
		ui.inputDevices->addItem(inDevMgr.getDeviceName(i));

	inDevMgr.select(ui.inputDevices->currentIndex());
	dev.open(ui.midiOutDevices->currentIndex());

	QObject::connect(&inputClock, SIGNAL(timeout()), this, SLOT(inputClockTick()));
	QObject::connect(&inDevMgr, SIGNAL(axisChanged(int,int)), this, SLOT(axisChanged(int,int)));
	QObject::connect(&inDevMgr, SIGNAL(keyDown(int)), this, SLOT(keyDown(int)));
	QObject::connect(&inDevMgr, SIGNAL(keyUp(int)), this, SLOT(keyUp(int)));
	QObject::connect(ui.midiOutDevices, SIGNAL(currentIndexChanged(int)), this, SLOT(OnMidiDevicesIndexChanged(int)));
	QObject::connect(ui.inputDevices, SIGNAL(currentIndexChanged(int)), this, SLOT(OnInputDevicesIndexChanged(int)));

	inputClock.setInterval(0);
	inputClock.start();
}

void PS3ToMidi::OnMidiDevicesIndexChanged(int index)
{
	if (!dev.open(index)) {
		QMessageBox::information(this, QString("Information"),
			QString("An Error Occurred trying to open the selected midi device."), 
			QMessageBox::Ok);
	}
}

void PS3ToMidi::OnInputDevicesIndexChanged(int id)
{
	try {
		inDevMgr.select(id);
	} catch (...) {
		QMessageBox::information(this, QString("Information"),
			QString("An Error Occurred trying to open the selected input device."), 
			QMessageBox::Ok);
	}
}

void PS3ToMidi::inputClockTick()
{
	inDevMgr.pollDevices();
}

void PS3ToMidi::axisChanged(int axis, int value)
{
	unsigned char cmdValue =
		(axis % 2) ? -(127 * value/65535.0) + 127 : (127 * value/65535.0);
	MidiMessage msg;
	msg.setStatus(ControlChange);
	msg.setChannel(0);
	msg.setParam0(axis);
	msg.setParam1(cmdValue);
	dev.sendMessage(msg);
	QString text;
	text.sprintf("Satus: %d | Channel: %d | Param0: %d | Param1: %d",
		msg.getStatus(), msg.getChannel(), msg.getParam0(), msg.getParam1());
	ui.debugInfo->setEnabled(false);
	ui.debugInfo->setText(text);
	this->update();
}

void PS3ToMidi::keyDown(int keyCode)
{
	if (keyCode == 0)
		Square_Down = true;
	if (keyCode == 1)
		Cross_Down = true;  
	if (keyCode == 2)
		Circle_Down = true;
	if (keyCode == 3)
		Triangle_Down = true;
	if (keyCode == 4)
		R1_Down = true;
	if (keyCode == 5)
		L1_Down = true;  
	if (keyCode == 6)
		R2_Down = true;
	if (keyCode == 7)
		L2_Down = true;  
	if (keyCode == 9)
		Start_Down = true;
	if (keyCode == 8)
		Select_Down = true;
	if (keyCode == 10)
		R3_Down = true;
	if (keyCode == 11)
		L3_Down = true;
	if (keyCode == 12)
		Home_Down = true;
	if (keyCode == 19)
		Up_Down = true;
	if (keyCode == 20)
		Right_Down = true;
	if (keyCode == 21)
		Down_Down = true;
	if (keyCode == 22)
		Left_Down = true;

	MidiMessage msg;
	msg.setStatus(ControlChange);
	msg.setChannel(0);
	msg.setParam0(keyCode);
	msg.setParam1(127);
	dev.sendMessage(msg);
	this->update();
}

void PS3ToMidi::keyUp(int keyCode)
{
	if (keyCode == 0)
		Square_Down = false;
	if (keyCode == 1)
		Cross_Down = false;  
	if (keyCode == 2)
		Circle_Down = false;
	if (keyCode == 3)
		Triangle_Down = false;
	if (keyCode == 4)
		R1_Down = false;
	if (keyCode == 5)
		L1_Down = false; 
	if (keyCode == 6)
		R2_Down = false;
	if (keyCode == 7)
		L2_Down = false;
	if (keyCode == 9)
		Start_Down = false;
	if (keyCode == 8)
		Select_Down = false;
	if (keyCode == 10)
		R3_Down = false;
	if (keyCode == 11)
		L3_Down = false;
	if (keyCode == 12)
		Home_Down = false;
	if (keyCode == 19)
		Up_Down = false;
	if (keyCode == 20)
		Right_Down = false;
	if (keyCode == 21)
		Down_Down = false;
	if (keyCode == 22)
		Left_Down = false;

	MidiMessage msg;
	msg.setStatus(ControlChange);
	msg.setChannel(0);
	msg.setParam0(keyCode);
	msg.setParam1(0);
	dev.sendMessage(msg);
	this->update();
}

void PS3ToMidi::paintEvent(QPaintEvent *e)
{
	QPainter painter(this);
	QImage _image(":/PS3ToMidi/BGIMAGE.PNG");
	painter.drawImage(0, 0, _image);
	QBrush activated(QColor(100, 100, 100, 200));
	painter.setBrush(activated);

	if (R1_Down)
		painter.drawRect(44, 30, 50, 32);
	if (L1_Down)
		painter.drawRect(295, 30, 50, 32);
	if (R2_Down) 
		painter.drawRect(44, 78, 50, 46);
	if (L2_Down) 
		painter.drawRect(295, 78, 50, 46);
	if (R3_Down) 
		painter.drawEllipse(QPoint(139, 273), 27, 28);
	if (L3_Down) 
		painter.drawEllipse(QPoint(261, 273), 27, 28);
	if (Start_Down) 
		painter.drawRect(226, 212, 21, 16);
	if (Select_Down) 
		painter.drawRect(156, 214, 16, 11);
	if (Circle_Down) 
		painter.drawEllipse(QPoint(352, 217), 12, 12);
	if (Cross_Down) 
		painter.drawEllipse(QPoint(318, 248), 12, 12);
	if (Square_Down) 
		painter.drawEllipse(QPoint(286, 217), 12, 12);
	if (Triangle_Down) 
		painter.drawEllipse(QPoint(318, 186), 12, 12);
	if (Home_Down) 
		painter.drawEllipse(QPoint(201, 242), 16, 16);
	if (Up_Down)
		painter.drawRect(72, 187, 20, 15);
	if (Down_Down) 
		painter.drawRect(72, 235, 20, 15);
	if (Left_Down)
		painter.drawRect(50, 208, 16, 20);
	if (Right_Down) 
		painter.drawRect(99, 208, 16, 20);
}

PS3ToMidi::~PS3ToMidi()
{
	dev.close();
}
